<html>
 <head>
  <meta charset="UTF-8">
 </head>
 <body>
  <h1 data-lake-id="sgt9K" id="sgt9K"><span data-lake-id="u2b3d4625" id="u2b3d4625">典型回答</span></h1>
  <p data-lake-id="u5d1a1c8c" id="u5d1a1c8c"><br></p>
  <p data-lake-id="u93fc1a1b" id="u93fc1a1b"><span data-lake-id="uf5b0329c" id="uf5b0329c">模板方法模式是一种行为设计模式，他的主要作用就是复用代码。在很多时候，我们的代码中可能会有一些公共的部分并且还有一些定制的部分，那么公共这部分就可以定义在一个父类中，然后将定制的部分实现在子类中。这样子类可以根据需要扩展或重写父类的方法，而不需要改变算法的结构。</span></p>
  <p data-lake-id="ua4514851" id="ua4514851"><span data-lake-id="uc08e7090" id="uc08e7090">​</span><br></p>
  <p data-lake-id="ub4d15698" id="ub4d15698"><span data-lake-id="u026212a4" id="u026212a4">我们通常会把模板方法模式和策略模式一起使用，因为当我们使用策略模式的时候，会把具体的策略实现在策略服务里面，但是还剩下一些通用的逻辑，就可以通过模板方法模式进行复用。</span></p>
  <p data-lake-id="ud2171534" id="ud2171534"><span data-lake-id="u644d55db" id="u644d55db">​</span><br></p>
  <p data-lake-id="u2856ed7d" id="u2856ed7d"><span data-lake-id="ua4f6ff8e" id="ua4f6ff8e">​</span><br></p>
  <h1 data-lake-id="ZeFqc" id="ZeFqc"><span data-lake-id="uc8d88e8d" id="uc8d88e8d">扩展知识</span></h1>
  <p data-lake-id="u4629ef9d" id="u4629ef9d"><br></p>
  <h2 data-lake-id="S0TP3" id="S0TP3"><span data-lake-id="ua96b2570" id="ua96b2570">示例</span></h2>
  <p data-lake-id="u6697f3e9" id="u6697f3e9"><br></p>
  <p data-lake-id="u07ae1240" id="u07ae1240"><span data-lake-id="u803a1946" id="u803a1946">我们拿一个常见的优惠券作为示例，假设我们需要定义一个优惠券的申请服务。</span></p>
  <p data-lake-id="u25f33e6a" id="u25f33e6a"><br></p>
  <pre lang="java"><code>
abstract class Coupon {
    // 模板方法，定义优惠券的应用流程
    public final void applyCoupon() {
        if (isCouponValid()) {
            if (isEligibleForDiscount()) {
                applyDiscount();
            }
            displayConfirmation();
        } else {
            displayInvalidCouponMessage();
        }
    }

    // 具体方法，用于判断优惠券是否有效
    protected boolean isCouponValid() {
        // 具体的判断逻辑，子类可以重写该方法来实现特定的有效性判断
        return true;
    }

    // 具体方法，用于判断用户是否符合优惠券的折扣条件
    protected boolean isEligibleForDiscount() {
        // 具体的判断逻辑，子类可以重写该方法来实现特定的条件判断
        return true;
    }

    // 抽象方法，由子类实现具体的优惠券折扣逻辑
    protected abstract void applyDiscount();

    // 抽象方法，由子类实现具体的优惠券确认展示逻辑
    protected abstract void displayConfirmation();

    // 具体方法，用于展示无效优惠券的信息
    protected void displayInvalidCouponMessage() {
        System.out.println("无效优惠券！");
    }
}
</code></pre>
  <p data-lake-id="u9e3e31c9" id="u9e3e31c9"><br></p>
  <p data-lake-id="u8f0ca6d7" id="u8f0ca6d7"><span data-lake-id="u6d43c771" id="u6d43c771">以上是一个抽象类，这个类中有一个具体的方法applyCoupon，其中定义了一个优惠券申请的具体实现，并且编排了多个其他的方法。</span></p>
  <p data-lake-id="u005d162f" id="u005d162f"><span data-lake-id="u177defe4" id="u177defe4">​</span><br></p>
  <p data-lake-id="u66c0d935" id="u66c0d935"><span data-lake-id="ub5fc7f01" id="ub5fc7f01">这就是一个典型的模板方法。我们可以基于这个抽象类来定义具体的实现：</span></p>
  <p data-lake-id="u54bbb05b" id="u54bbb05b"><span data-lake-id="ub8934736" id="ub8934736">​</span><br></p>
  <pre lang="java"><code>
class PercentageCoupon extends Coupon {
    @Override
    protected void applyDiscount() {
        // 具体的百分比折扣逻辑
        System.out.println("应用百分比折扣优惠！");
    }

    @Override
    protected void displayConfirmation() {
        // 具体的百分比优惠券确认展示逻辑
        System.out.println("百分比折扣优惠确认！");
    }
}


class FixedAmountCoupon extends Coupon {
    @Override
    protected void applyDiscount() {
        // 具体的固定金额折扣逻辑
        System.out.println("应用固定金额优惠！");
    }

    @Override
    protected void displayConfirmation() {
        // 具体的固定金额优惠券确认展示逻辑
        System.out.println("固定金额优惠确认！");
    }
}

</code></pre>
  <p data-lake-id="u72a690da" id="u72a690da"><br></p>
  <p data-lake-id="ua9d98858" id="ua9d98858"><br></p>
  <p data-lake-id="u27676d54" id="u27676d54"><span data-lake-id="ufbc69562" id="ufbc69562">以上，就是两个具体的实现，分别继承Coupon抽象类，并且实现其中的部分方法就行了。</span></p>
  <p data-lake-id="uc81b7b78" id="uc81b7b78"><span data-lake-id="u2bfb232d" id="u2bfb232d">​</span><br></p>
  <p data-lake-id="ub5968548" id="ub5968548"><span data-lake-id="ud14b8526" id="ud14b8526">这样我们在实际使用时，就可以直接用FixedAmountCoupon和PercentageCoupon类，并且直接调用他的applyCoupon方法就行了。如：</span></p>
  <p data-lake-id="u3dc5a799" id="u3dc5a799"><span data-lake-id="u9d6a5c21" id="u9d6a5c21">​</span><br></p>
  <pre lang="java"><code>
public class Main {
    public static void main(String[] args) {
        Coupon percentageCoupon = new PercentageCoupon();
        percentageCoupon.applyCoupon();

        System.out.println("----------------");

        Coupon fixedAmountCoupon = new FixedAmountCoupon();
        fixedAmountCoupon.applyCoupon();
    }
}
</code></pre>
  <p data-lake-id="ud356d053" id="ud356d053"><br></p>
  <p data-lake-id="ub51bcc3b" id="ub51bcc3b"><br></p>
 </body>
</html>